package com.xncoding.pos.interceptor;//package com.autoai.wechatgroup.interceptor;

import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.*;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;

import java.io.StringReader;
import java.sql.Connection;
import java.util.List;
import java.util.Properties;

/**
 * 注解中的Signature决定了你的代码对哪些方法拦截，update实际上针对修改（Update）、删除（Delete）生效，(包括增删改)
 * query是对查询（Select）生效。
 */
@Component
@Slf4j
@Intercepts({@Signature(method = "prepare", type = StatementHandler.class, args = {Connection.class, Integer.class})})
// @Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
//         @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class SqlInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        log.info(">>>>>>>>>>>>>>>>mybatis拦截器>>>>>>>>>>>>>");

        StatementHandler handler = (StatementHandler) invocation.getTarget();

        MetaObject statementHandler = SystemMetaObject.forObject(handler);
        MappedStatement mappedStatement = (MappedStatement) statementHandler.getValue("delegate.mappedStatement");

        //获得方法类型 (如select,update)
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        if (SqlCommandType.SELECT.toString().equalsIgnoreCase(sqlCommandType.toString())) {
            //获取sql
            BoundSql boundSql = handler.getBoundSql();
            String sql = boundSql.getSql();
            //将增强后的sql放回
            statementHandler.setValue("delegate.boundSql.sql", sql);
        }

        // // 改变sql语句
        // BoundSql newBoundSql = new BoundSql(mappedStatement.getConfiguration(), oldsql + " and id=1",
        //         boundSql.getParameterMappings(), boundSql.getParameterObject());
        // MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql));
        // invocation.getArgs()[0] = newMs;
        //
        // log.info("新的sql:" + newBoundSql.getSql());


        // 继续执行
        Object result = invocation.proceed();
        return result;
    }


    /**
     * 返回默认的值，list类型的返回空list,数值类型的返回0
     *
     * @param invocation
     * @return
     */
    private Object getDefaultReturnValue(Invocation invocation) {
        Class returnType = invocation.getMethod().getReturnType();
        if (returnType.equals(List.class)) {
            return Lists.newArrayList();
        } else if (returnType.equals(Integer.TYPE) || returnType.equals(Long.TYPE)
                || returnType.equals(Integer.class) || returnType.equals(Long.class)) {
            return 0;
        }
        return null;
    }

    // 复制原始MappedStatement
    private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
        MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource,
                ms.getSqlCommandType());
        builder.resource(ms.getResource());
        builder.fetchSize(ms.getFetchSize());
        builder.statementType(ms.getStatementType());
        builder.keyGenerator(ms.getKeyGenerator());
        if (ms.getKeyProperties() != null) {
            for (String keyProperty : ms.getKeyProperties()) {
                builder.keyProperty(keyProperty);
            }
        }
        builder.timeout(ms.getTimeout());
        builder.parameterMap(ms.getParameterMap());
        builder.resultMaps(ms.getResultMaps());
        builder.cache(ms.getCache());
        builder.useCache(ms.isUseCache());
        return builder.build();
    }


    @Override
    public Object plugin(Object target) {
        // 当目标类是StatementHandler类型时，才包装目标类，否者直接返回目标本身,减少目标被代理的次数
        // return Plugin.wrap(target, this);
        return (target instanceof RoutingStatementHandler) ? Plugin.wrap(target, this) : target;
    }


    @Override
    public void setProperties(Properties properties) {

    }

}
